package com.hymall.service.wx;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hymall.bean.*;
import com.hymall.bean.common.BasePageInfo;
import com.hymall.bean.common.CommonData;
import com.hymall.bean.vo.WxCouponVo;
import com.hymall.mapper.MarketCouponMapper;
import com.hymall.mapper.MarketCouponUserMapper;
import com.hymall.mapper.MarketUserMapper;
import com.hymall.mapper.UserMapper;
import com.hymall.util.DateUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author: 叶熠彬
 * @description: 用户优惠券相关操作
 * @date: 2022/7/19 11:04
 */
@Service
public class WxCouponServiceImpl implements WxCouponService {

    @Autowired
    MarketCouponUserMapper couponUserMapper;
    @Autowired
    MarketCouponMapper couponMapper;

    @Autowired
    MarketUserMapper userMapper;

    /**
     * 根据state查找不同状态的优惠券，分页显示
     * state = -1，查询该用户所有状态的优惠券
     * TODO 根据每次查看时的时间刷新状态码
     *
     * @author: 叶熠彬
     * @date: 2022/7/19 11:15
     * @param: [status, info]
     * @return: com.hymall.bean.common.CommonData
     */
    @Override
    public CommonData queryCouponList(Integer userId, int status, BasePageInfo info) {

        PageHelper.startPage(info.getPage(), info.getLimit());
        PageHelper.orderBy("update_time" + " " + "desc");
        Date nowTime = new Date();
        MarketCouponUserExample example = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = example.createCriteria();
        //state = -1，查询该用户所有状态的优惠券
        if (status != -1) {
            criteria.andStatusEqualTo((short) status);
        }
        criteria.andDeletedEqualTo(false);
        criteria.andUserIdEqualTo(userId);
        //根据status查到所有coupon_user表里的数据，根据里面的优惠券Id找coupon表
        List<MarketCouponUser> marketCouponUsers = couponUserMapper.selectByExample(example);
        ArrayList<MarketCouponUser> newUserCoupon = new ArrayList<>();
        for (MarketCouponUser marketCouponUser : marketCouponUsers) {
            //根据当前时间检查未使用的是否超时
            if (marketCouponUser.getStatus() == 0) {
                if (marketCouponUser.getEndTime().before(nowTime)) {
                    marketCouponUser.setStatus((short) 2);
                    couponUserMapper.updateByPrimaryKey(marketCouponUser);
                }
            }
            if (status == marketCouponUser.getStatus()) {
                newUserCoupon.add(marketCouponUser);
            }
        }
        ArrayList<WxCouponVo> vos = getWxCouponVos(newUserCoupon);
        PageInfo<WxCouponVo> pageInfo = new PageInfo<>(vos);
        return CommonData.data(pageInfo);
    }


    /**
     * 根据兑换码兑换优惠券
     * 增加事务管理，查询数量后，若添加给用户/减少优惠券数量失败回滚(insert/update)
     *
     * @author: 叶熠彬
     * @date: 2022/7/19 12:06
     * @param: [code]
     * @return: int
     */
    @Transactional
    @Override
    public int addCouponByCode(String code) {
        //根据code在coupon表查找兑换的优惠券
        List<MarketCoupon> marketCoupons = getMarketCouponsByCode(code);
        if (marketCoupons.size() == 0) {
            //兑换码不存在 或库存不足
            return 742;
        }
        if (marketCoupons.size() > 1) {
            //错误
            return 743;
        }
        MarketCoupon marketCoupon = marketCoupons.get(0);
        if (hasReceived(marketCoupon)) return 740;
        //添加给user
        Subject subject = SecurityUtils.getSubject();
        MarketUser user = (MarketUser) subject.getPrincipal();
        MarketCouponUser couponUser = createCouponUser(marketCoupon, user.getId());
        couponUserMapper.insertSelective(couponUser);
        MarketCouponExample couponExample = new MarketCouponExample();
        couponExample.createCriteria().andIdEqualTo(marketCoupon.getId());
        couponMapper.updateByExampleSelective(marketCoupon, couponExample);

        return 200;
    }

    /**
     * 优惠券专区：前台查询后台优惠券信息
     * 查询MarketCoupon对象
     * TODO 待测
     *
     * @author: 叶熠彬
     * @date: 2022/7/19 22:25
     * @param: [info]
     * @return: com.hymall.bean.common.CommonData
     */
    @Override
    public CommonData queryWxAvailableCoupon(BasePageInfo info) {
        PageHelper.startPage(info.getPage(), info.getLimit());
        PageHelper.orderBy("update_time desc");
        MarketCouponExample example = new MarketCouponExample();
        MarketCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false);
        criteria.andTotalGreaterThanOrEqualTo(0);
        criteria.andTypeEqualTo((short) 0);
        criteria.andStatusEqualTo((short) 0);
        List<MarketCoupon> marketCoupons = couponMapper.selectByExample(example);
        PageInfo<MarketCoupon> pageInfo = new PageInfo<>(marketCoupons);

        return CommonData.data(pageInfo);
    }

    /**
     * 在购物车下单页面查询用户优惠券中available的优惠券
     * TODO 待测 时间更新和商品、类目限制问题
     *
     * @author: 叶熠彬
     * @date: 2022/7/19 23:45
     * @param: [userId]
     * @return: com.hymall.bean.common.CommonData
     */
    @Override
    public CommonData queryCartAvailableCoupon(Integer userId) {
        MarketCouponUserExample example = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false);
        //使用状态, 如果是0则未使用；如果是1则已使用；如果是2则已过期；如果是3则已经下架；
        criteria.andStatusEqualTo((short) 0);
        criteria.andUserIdEqualTo(userId);
        List<MarketCouponUser> marketCouponUsers = couponUserMapper.selectByExample(example);
        ArrayList<WxCouponVo> vos = new ArrayList<>();
        for (MarketCouponUser marketCouponUser : marketCouponUsers) {
            Integer couponId = marketCouponUser.getCouponId();
            Integer id = marketCouponUser.getId();
            MarketCoupon marketCoupon = couponMapper.selectByPrimaryKey(couponId);
            WxCouponVo vo = new WxCouponVo();
            BeanUtils.copyProperties(marketCoupon, vo);
            //显示用户的优惠券时间信息
            vo.setStartTime(marketCouponUser.getStartTime());
            vo.setEndTime(marketCouponUser.getEndTime());
            vo.setCid(couponId);
            //marketCouponUser.getStatus使用状态, 如果是0则未使用；如果是1则已使用；如果是2则已过期；如果是3则已经下架；
            if (marketCouponUser.getStatus() == 0 && marketCouponUser.getEndTime().after(new Date())) {
                vo.setAvailable(true);
                vo.setId(id);
                vos.add(vo);
            } else {
                vo.setAvailable(false);
            }
        }
        PageInfo<WxCouponVo> pageInfo = new PageInfo<>(vos);

        return CommonData.data(pageInfo);
    }

    /**
     * 优惠券专区领取优惠券，写入coupon_user表
     * 返回状态码判断领取状态
     *
     * @author: 叶熠彬
     * @date: 2022/7/20 10:07
     * @param: [couponId]
     * @return: int
     */
    @Override
    public int receiveCoupon(Integer couponId) {
        MarketCouponExample couponExample = new MarketCouponExample();
        MarketCouponExample.Criteria couponExampleCriteria = couponExample.createCriteria();
        couponExampleCriteria.andIdEqualTo(couponId);
        List<MarketCoupon> marketCoupons = couponMapper.selectByExample(couponExample);
        if (marketCoupons.size() == 0) {
            //兑换码不存在 或库存不足
            return 742;
        }
        if (marketCoupons.size() > 1) {
            //错误
            return 743;
        }
        MarketCoupon marketCoupon = marketCoupons.get(0);
        if (hasReceived(marketCoupon)) {
            //已经领取过
            return 740;
        }
        //登陆后才能进入这个方法，就不判空了
        Subject subject = SecurityUtils.getSubject();
        MarketUser user = (MarketUser) subject.getPrincipal();

        MarketCouponUser couponUser = createCouponUser(marketCoupon, user.getId());
        couponUserMapper.insertSelective(couponUser);
        return 0;
    }

    /**
     * 给新注册用户发放新人优惠券
     *
     * @author: 叶熠彬
     * @date: 2022/7/21 21:37
     * @param: [wxCode]
     * @return: int
     */
    @Override
    public int addNewUserCoupon(String wxCode) {
        //找用户
        MarketUserExample userExample = new MarketUserExample();
        userExample.createCriteria().andWeixinOpenidEqualTo(wxCode);
        List<MarketUser> marketUsers = userMapper.selectByExample(userExample);
        Integer userId = marketUsers.get(0).getId();
        //找优惠券
        MarketCouponExample couponExample = new MarketCouponExample();
        //coupon type=1，注册送券
        couponExample.createCriteria().andTypeEqualTo((short) 1);
        List<MarketCoupon> marketCoupons = couponMapper.selectByExample(couponExample);
        for (MarketCoupon marketCoupon : marketCoupons) {
            MarketCouponUser couponUser = createCouponUser(marketCoupon, userId);
            couponUserMapper.insertSelective(couponUser);
        }
        return 0;
    }

    /**
     * 根据code在coupon表查找兑换的优惠券
     * 应该只有一张
     *
     * @author: 叶熠彬
     * @date: 2022/7/19 15:06
     * @param: [code]
     * @return: java.util.List<com.hymall.bean.MarketCoupon>
     */
    private List<MarketCoupon> getMarketCouponsByCode(String code) {
        MarketCouponExample couponExample = new MarketCouponExample();
        MarketCouponExample.Criteria couponExampleCriteria = couponExample.createCriteria();
        couponExampleCriteria.andDeletedEqualTo(false);
        //优惠券类型为可兑换类型
        couponExampleCriteria.andTypeEqualTo((short) 2);
        //优惠券状态可用
        couponExampleCriteria.andStatusEqualTo((short) 0);
        //数量>0，可领取；数量=0，不限量；-1，领完了
        couponExampleCriteria.andTotalNotEqualTo(-1);
        //兑换码
        if (code != null && !"".equals(code)) {
            couponExampleCriteria.andCodeEqualTo(code);
        }
        return couponMapper.selectByExample(couponExample);
    }


    /**
     * 根据查到的优惠券信息
     * 创建写入数据库的MarketCouponUser
     *
     * @author: 叶熠彬
     * @date: 2022/7/19 15:57
     * @param: [marketCoupon]
     * @return: void
     */
    private MarketCouponUser createCouponUser(MarketCoupon marketCoupon, Integer userId) {
        MarketCouponUser couponUser = new MarketCouponUser();
        couponUser.setAddTime(new Date());
        couponUser.setUserId(userId);
        couponUser.setCouponId(marketCoupon.getId());
        couponUser.setStatus((short) 0);
        Date startDay = new Date();
        //基于领取时间的有效天数days
        if (marketCoupon.getTimeType() == 0) {
            Date endDay = DateUtils.addDays(marketCoupon.getDays(), startDay);
            couponUser.setStartTime(startDay);
            couponUser.setEndTime(endDay);
        }
        //则start_time和end_time是优惠券有效期
        if (marketCoupon.getTimeType() == 1) {
            couponUser.setStartTime(marketCoupon.getStartTime());
            couponUser.setEndTime(marketCoupon.getEndTime());
        }
        couponUser.setAddTime(startDay);
        couponUser.setUpdateTime(startDay);
        couponUser.setDeleted(false);
        return couponUser;
    }

    /**
     * 根据type=可领取的优惠券领取数量限制判断用户是否可以继续领取
     * 如果可领取返回false，更改优惠券库存数量
     *
     * @author: 叶熠彬
     * @date: 2022/7/20 10:22
     * @param: [marketCoupon]
     * @return: boolean
     */
    private boolean hasReceived(MarketCoupon marketCoupon) {
        Short limit = marketCoupon.getLimit();
        //有领取数量限制，user是否可兑换优惠券
        if (limit != 0) {
            //TODO 要不要判断deleted
            MarketCouponUserExample couponUserExample = new MarketCouponUserExample();
            MarketCouponUserExample.Criteria userExampleCriteria = couponUserExample.createCriteria();
            //通过couponID判断优惠券是否领取过
            userExampleCriteria.andCouponIdEqualTo(marketCoupon.getId());
            List<MarketCouponUser> marketCouponUsers = couponUserMapper.selectByExample(couponUserExample);
            if (marketCouponUsers.size() != 0) {
                //已经领取过
                return true;
            }
        }
        //可以领取多张，根据优惠券库存数量，user领取优惠券
        Integer stockNum = marketCoupon.getTotal();

        if (stockNum > 1) {
            //限量优惠券数量-1
            marketCoupon.setTotal(stockNum - 1);
        }
        if (stockNum == 1) {
            //领取完最后一张，用-1表示
            marketCoupon.setTotal(-1);
        }
        return false;
    }

    /**
     * 根据用户优惠券列表查找商城优惠券
     * 返回VO对象
     *
     * @author: 叶熠彬
     * @date: 2022/7/19 21:49
     * @param: [marketCouponUsers]
     * @return: java.util.ArrayList<com.hymall.bean.vo.WxCouponVo>
     */
    private ArrayList<WxCouponVo> getWxCouponVos(List<MarketCouponUser> marketCouponUsers) {
        ArrayList<WxCouponVo> vos = new ArrayList<>();
        for (MarketCouponUser marketCouponUser : marketCouponUsers) {
            Integer couponId = marketCouponUser.getCouponId();
            Integer id = marketCouponUser.getId();
            WxCouponVo vo = new WxCouponVo();
            MarketCoupon marketCoupon = couponMapper.selectByPrimaryKey(couponId);
            BeanUtils.copyProperties(marketCoupon, vo);
            //显示用户的优惠券时间信息
            vo.setStartTime(marketCouponUser.getStartTime());
            vo.setEndTime(marketCouponUser.getEndTime());
            vo.setCid(couponId);
            //marketCouponUser.getStatus使用状态, 如果是0则未使用；如果是1则已使用；如果是2则已过期；如果是3则已经下架；
            if (marketCouponUser.getStatus() == 0) {
                vo.setAvailable(true);
            }
            vo.setAvailable(false);
            vo.setId(id);
            vos.add(vo);
        }
        return vos;
    }

}
